home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Archives / ARexxTools / ScionRexx.lha / PrintPedigree.rexx < prev    next >
Encoding:
OS/2 REXX Batch file  |  1995-10-31  |  23.0 KB  |  816 lines

  1. /****************************************************************************
  2.  *                                                                          *
  3.  * $VER: PrintPedigree 2.05 (30 Oct 1995)
  4.  *                                                                          *
  5.  *                      Written by Freddy Ariës                             *
  6.  * Address: Lindeboomweg 7, NL-7135 KE Harreveld, The Netherlands.          *
  7.  *                                                                          *
  8.  * Output options:                                                          *
  9.  *  1. Forefathers (male ancestor line only)       [Dutch: stamreeks]       *
  10.  *  2. Pedigree Chart; no siblings                 [Dutch: kwartierstaat]   *
  11.  *  3. Pedigree Chart; only siblings of proband  (= of youngest generation) *
  12.  *  4. Pedigree Chart; all siblings                                         *
  13.  *                                                                          *
  14.  * This script uses (by default) the rexxreqtools.library (which requires   *
  15.  * a version of reqtools larger than 2.0 and rexxsyslib.library)            *
  16.  * If you do not have these, run SetDefaults.rexx to change the settings.   *
  17.  *                                                                          *
  18.  * As of v2 of this script, and Scion V4, the current person on Scion's     *
  19.  * Personal Window will be used to determine where the search starts.       *
  20.  * Scion 3.13 can still be used, though, in which case the user will be     *
  21.  * asked at which IRN he wants to start.                                    *
  22.  *                                                                          *
  23.  * So why this PrintPedigree script when Scion already has a print option   *
  24.  * for pedigree charts? Well, the reason is simple: the format of the       *
  25.  * pedigree charts generated by Scion does not conform to the guidelines    *
  26.  * of the Dutch CBG (Central Bureau for Genealogy) and NGV (Nederlandse     *
  27.  * Genealogische Vereniging; Dutch Genealogical Society). So I created my   *
  28.  * own PrintPedigree script, that *does* follow their guidelines.           *
  29.  *                                                                          *
  30.  * DONE:                                                                    *
  31.  *  - Now uses preference file for default settings                         *
  32.  *  - count the number of lines output and give a formfeed after a          *
  33.  *    certain number (ie. skip page breaks)                                 *
  34.  *                                                                          *
  35.  * TO DO (low priority, unless someone really wants this):                  *
  36.  *  - add a menu option for the maximum number of generations to print      *
  37.  *  - allow user to specify if he wants burial data, occupation, comments,  *
  38.  *    references fields, etc. printed                                       *
  39.  *  - option: include empty fields                                          *
  40.  *  - find a good way to handle sex-fields with value '?' (see below)       *
  41.  *  - Suggestions, comments, bugreports, donations, etc. are appreciated.   *
  42.  *                                                                          *
  43.  * Known Bugs/Problems:                                                     *
  44.  *  - This script is dog slow for large databases (ie. more than, say, 10   *
  45.  *    generations), even on Amigas with a Turboboard!                       *
  46.  *  - Incorrect assumptions may be made (with regard to father/mother) when *
  47.  *    there are persons in the database whose sex-field has value '?'       *
  48.  *                                                                          *
  49.  ****************************************************************************/
  50.  
  51. options results
  52. arg prtin outname noirn mgen outval
  53.  
  54. versionstr = "2.05"
  55.  
  56. /* Don't change the settings here! Run SetDefaults.rexx instead! */
  57. usereq = 1; outp = 1; useirn = 1
  58. prtdev = stdout; prtopt = 0; scrdev = stdout
  59. plwidth = 78; pgsize = 0
  60. PSCR = 'SCIONGEN'
  61.  
  62. scrname = "CON:0//639//Scion Output/AUTO/SCREEN"
  63. prtrev = 0;    /* prtrev = 0 means youngest (first) generation = I */
  64.         /* prtrev = 1 means oldest (last) generation = I */
  65. DbtGen = 10;
  66.   /* Suggested value for 68000: 10, with Turbo-boards: 12
  67.    * From this generation onwards, every additional generation needs a confirm
  68.    * Note: 10 generations means (up to) 1024 persons,
  69.    * 12 generations means (up to) 4096 persons !!!
  70.    */
  71. pgline = 1
  72. NL = '0A'x
  73.  
  74. signal on IOERR
  75.  
  76. /* parse command line options, to allow calling the script automatically,
  77.  * eg. from a function key
  78.  */
  79.  
  80. do while prtin = '?'
  81.   Tell("NUMOPT/A/N,OUTFILE/A,NOIRN/S,MAXGEN/N,QUIET/S,NOREQ/S: ")
  82.   pull prtin outname noirn mgen outval
  83. end
  84.  
  85. /* read preferences file */
  86.  
  87. if open(pfile, 'ENV:Scion/ScionRexx.prefs', 'r') then do
  88.   do while ~eof(pfile)
  89.     inln = readln(pfile)
  90.     if inln ~= "" then do
  91.       wstr = upper(word(inln, 1))
  92.       if wstr = "USEREQ" then
  93.         usereq = 1
  94.       else if wstr = "NOUSEREQ" then
  95.         usereq = 0
  96.       else if wstr = "PUBSCREEN" then
  97.         pscr = strip(delstr(inln, 1, length(wstr)), 'b', ' "')
  98.       else if wstr = "LINEWIDTH" then do
  99.         wstr = word(inln, 2)
  100.         if datatype(wstr, 'w') then plwidth = wstr
  101.       end
  102.       else if wstr = "PAGESIZE" then do
  103.         wstr = word(inln, 2)
  104.         if datatype(wstr, 'w') then pgsize = wstr
  105.       end
  106.     end
  107.   end
  108.   close(pfile)
  109. end
  110.  
  111. if pscr = "" | (pscr ~= "WORKBENCH" & ~show('p', pscr)) then
  112.   pscr = "SCIONGEN"
  113. scrname = scrname||pscr
  114.  
  115. /* Command line options get priority over global settings */
  116. ParseArguments()
  117.  
  118. if ~show('l','rexxarplib.library') then do
  119.   if exists('libs:rexxarplib.library') then
  120.     call addlib('rexxarplib.library',0,-30,0)
  121. end
  122.  
  123. screentofront(pscr)
  124.  
  125. if usereq & ~show('l','rexxreqtools.library') then do
  126.   if exists('libs:rexxreqtools.library') then
  127.     call addlib('rexxreqtools.library',0,-30,0)
  128.   else do
  129.     usereq = 0; outp = 1
  130.     Tell("Unable to open rexxreqtools.library - using text output")
  131.   end
  132. end
  133.  
  134. /* Originally stolen from Peter Billing - thanks Peter ;-) */
  135. if ~show('P','SCIONGEN') then do
  136.   EndString('I am sorry to say that the SCION Genealogist' || NL ||,
  137.     'database is not available. Please start the' || NL ||,
  138.     'SCION program BEFORE using this script!')
  139. end
  140.  
  141. myport = "SCIONGEN"
  142. address value myport
  143. GETDBNAME
  144. dbname = upper(RESULT)
  145. GETPROGVERSION
  146. progvers = RESULT
  147.  
  148. if progvers >= 4 then do
  149.   GETCURRENTIRN
  150.   irn = RESULT
  151. end
  152.  
  153. if outp & ~usereq then do
  154.   if pscr ~= "WORKBENCH" then do
  155.     scrdev = 'SCNPEDSCR'
  156.     if ~open(scrdev, scrname, 'w') then scrdev = stdout
  157.   end
  158.   Tell("*** PrintPedigree version "||versionstr||" ***")
  159.   Tell("***       by Freddy Ariës      ***")
  160.   Tell("Current database: "||dbname||NL)
  161. end
  162. if prtopt = 0 then do
  163.   /* No use in asking for input if we're not allowed to output anything */
  164.   if usereq then do
  165.     prtopt = rtezrequest('Current Scion database: '||dbname||NL||,
  166.       NL||'Please make your choice: '||,
  167.       NL||'1. Forefathers (male ancestor line only)'||,
  168.       NL||'2. Pedigree Chart; no siblings'||,
  169.       NL||'3. Pedigree Chart; only siblings of proband'||,
  170.       NL||'4. Pedigree Chart; all siblings'||,
  171.       '',' _1 | _2 | _3 | _4 |E_xit','PrintPedigree v'||versionstr||' by Freddy Ariës','rt_pubscrname = '||PSCR)
  172.     if prtopt = 0 then EXIT
  173.  
  174.     if progvers < 4 then do
  175.       irn = rtgetlong(,'Enter the IRN of the person whose'||,
  176.             NL||'ancestors you want to print: '||,
  177.             NL,'Input Request:','_Continue','rt_pubscrname = '||PSCR)
  178.       if irn = '' then EndString("No IRN - aborted.")
  179.       irn = abs(irn)
  180.     end
  181.  
  182.     useirn = rtezrequest('Do you want to output the IRNs'||,
  183.               NL||'(the record numbers) as well?'||,
  184.               '',' _Yes| _No ','Input Request:','rt_pubscrname = '||PSCR)
  185.   end
  186.   else do
  187.     Tell("1. Forefathers (male ancestor line only)")
  188.     Tell("2. Pedigree Chart; no siblings")
  189.     Tell("3. Pedigree Chart; only siblings of proband")
  190.     Tell("4. Pedigree Chart; all siblings")
  191.     TellNN("Your choice: ")
  192.     prtopt = readln(scrdev)
  193.     prtopt = CheckAnswer(word(prtopt,1))
  194.  
  195.     if progvers < 4 then do
  196.       TellNN("Enter the IRN of the person whose ancestors you want to print: ")
  197.       irn = readln(scrdev)
  198.       irn = word(irn, 1)
  199.     end
  200.  
  201.     TellNN("Do you want to output the IRN (numbers) as well (y/n)? ")
  202.     instr = readln(scrdev)
  203.     instr = upper(left(instr, 1))
  204.     Tell("")
  205.     if instr = "Y" then useirn = 1
  206.     else useirn = 0
  207.   end
  208. end
  209.  
  210. if progvers < 4 & ~DATATYPE(irn, 'w') then
  211.   EndString("ERROR: Not a valid IRN: "||irn)
  212.  
  213. EXISTPERSON irn
  214. if RESULT ~= 'YES' then
  215.   EndString("No person with IRN "||irn||" in the current database.")
  216.  
  217. if outp then do
  218.   pname = GetNameStr(irn, 0)
  219.   if usereq then do
  220.     valcont = rtezrequest('The selected person is: '||NL||pname||'.'||,
  221.       NL||'Continue?','_Continue| _Abort','PrintPedigree Request:','rt_pubscrname = '||PSCR)
  222.     if valcont = 0 then EndString("Aborted.")
  223.   end
  224.   else do
  225.     TellNN("Current person is "||pname||". Continue? (y/n) ")
  226.     valcont = readln(scrdev)
  227.     valcont = upper(left(valcont, 1))
  228.     if valcont ~= 'Y' then EndString("Ok.")
  229.   end
  230. end
  231.  
  232. if outp & outname = "" then do
  233.   if usereq then do
  234.     odev = rtezrequest('Current Scion database: '||dbname||,
  235.       NL||'Where should the output be sent to?'||,
  236.       NL,' _File |_Printer|_Screen|_Nowhere','PrintPedigree v'||versionstr||' by Freddy Ariës','rt_pubscrname = '||PSCR)
  237.     select
  238.       when odev = 1 then do
  239.         /* We need a file requester for further data */
  240.         dblen = length(dbname)
  241.         if dblen>6 & right(dbname, 6)=".SCION" then
  242.           dbname=left(dbname, dblen - 6)
  243.         outname = rtfilerequest(,dbname||'.PED','Output filename',,'rtfi_buffer = true   rt_pubscrname = '||PSCR||'   rtfi_initialpath = RAM:',)
  244.         if outname = '' then
  245.           outname = dbname||'.PED'
  246.       end
  247.       when odev = 2 then
  248.         outname = 'PRT:'
  249.       when odev = 3 then
  250.         outname = 'STDOUT'
  251.       otherwise EndString("No output - aborted.")
  252.         /* You selected 'Nowhere' */
  253.     end
  254.   end
  255.   else do
  256.     Tell("Enter output file (filename with complete path, or PRT: for printer,")
  257.     TellNN("or STDOUT for screen): ")
  258.     outname = readln(scrdev)
  259.     outname = strip(outname, 'b', ' "')
  260.     if outname = "" then outname = 'STDOUT'
  261.   end
  262. end
  263.  
  264. /* Anyone know a better way to translate numbers into Roman? */
  265. GenerationS.1 = "I II III IV V VI VII VIII IX X XI XII XIII XIV XV XVI XVII XVIII XIX XX"
  266. GenerationS.2 = "XXI XXII XXIII XXIV XXV XXVI XXVII XXVIII XXIX XXX XXXI XXXII XXXIII XXXIV XXXV XXXVI XXXVII XXXVIII IXL XL"
  267.  
  268. /* Printer Codes (some of which are currently unused): */
  269. ESC = '1B'x
  270. prtinit = ESC||"#1";     /* ESC#1 initialize      */
  271. prtundon = ESC||"[4m";   /* ESC[4m underline on   */
  272. prtundoff = ESC||"[24m"; /* ESC[24m underline off */
  273. prtdson = ESC||"[1m";    /* ESC[1m boldface on    */
  274. prtdsoff = ESC||"[22m";  /* ESC[22m boldface off  */
  275. prtnlqon = ESC||"[2"||'22'x||"z";  /* ESC[2"z NLQ on  */
  276. prtnlqoff = ESC||"[1"||'22'x||"z"; /* ESC[1"z NLQ off */
  277.  
  278. if ~usereq then
  279.   Tell("Building ancestor table...")
  280.  
  281. currgen = 1; numpers = 1
  282. GENTREE.1 = irn
  283.  
  284. /* Build the ancestor table */
  285. do until ~foundone
  286.   foundone = 0
  287.   currgen = currgen + 1
  288.   numpers = 2 * numpers
  289.   /* = 2 ** (currgen - 1) */
  290.   if currgen <= MaxGens then
  291.   do
  292.     if currgen > DbtGen then
  293.     do
  294.       if usereq then
  295.       do
  296.         docont = rtezrequest('Also parse generation '||currgen||' ?'||,
  297.               NL||'(this may take *very* long!)'||,
  298.               '',' _Yes| _No ','Input Request:','rt_pubscrname = '||PSCR)
  299.       end
  300.       else
  301.       do
  302.         Tell("Also parse generation '||currgen||' ?' (this may take *very* long!)")
  303.         inp = readln(scrdev)
  304.         inp = upper(left(inp, 1))
  305.         Tell("")
  306.         if inp = "Y" then docont = 1
  307.         else docont = 0
  308.       end
  309.     end
  310.     else docont = 1
  311.  
  312.     if docont then
  313.     do
  314.       if prtopt = 1 then
  315.         endnum = numpers+1
  316.         /* no use to build the entire table, if we need only this little */
  317.       else
  318.         endnum = 2*numpers-1
  319.       /*
  320.        * TO DO: at the moment, all the numbers are parsed, even if there
  321.        *  is only one family group with ancestors in this generation
  322.        *  This means that thousands of fields may be checked, to find
  323.        *  two persons. This also makes the program dog slow!
  324.        *  I must find a better method to do this. Suggestions welcome...
  325.        */
  326.       do ct = numpers to endnum by 2
  327.         ct1 = ct % 2
  328.         irn = GENTREE.ct1
  329.         ct1 = ct + 1
  330.         GENTREE.ct = 0
  331.         GENTREE.ct1 = 0
  332.         if irn ~= 0 then do
  333.           GETPARENTS irn
  334.           fgrn = RESULT
  335.           EXISTFAMILY fgrn
  336.           if RESULT = 'YES' then do
  337.             foundone = 1
  338.             GetParentsIRN(fgrn, ct, ct1)
  339.           end
  340.         end
  341.       end
  342.     end
  343.   end
  344.   else do
  345.     if usereq then
  346.       rtezrequest('Maximum number of'||NL||'generations reached.'||NL||,
  347.     NL||'Output truncated','_Continue','PrintPedigree Message:','rt_pubscrname = '||PSCR)
  348.     else
  349.      Tell("Maximum number of generations reached. Output may be truncated.")
  350.   end
  351. end
  352. numgens = currgen - 1
  353.  
  354. /* Now print all the ancestors */
  355. if ~usereq then
  356.   Tell("Printing data...")
  357.  
  358. OpenPrinter()
  359.  
  360. if prtopt = 1 then do
  361.   /* Forefathers; print only male ancestors */
  362.   fill = 7
  363.   np = numpers%2
  364.   if prtrev then
  365.     currgen = currgen - 1
  366.   else
  367.     currgen = 1
  368.   do while np > 1
  369.     g1 = GetGenStr(currgen, fill)
  370.     ct1 = np + 1
  371.     ct2 = np % 2
  372.     /* get the husband's data */
  373.     g1 = g1||GetPersonStr(GENTREE.np)
  374.  
  375.     GETPARENTS GENTREE.ct2
  376.     mf1 = RESULT
  377.     EXISTFAMILY mf1
  378.     if RESULT = 'YES' then
  379.       m1 = GetMarriageStr(mf1)
  380.     else
  381.       m1 = ""
  382.  
  383.     if m1 ~= "" then
  384.       m1 = g1||", m: "||m1
  385.     else m1 = g1
  386.     g1 = copies(' ',fill)
  387.     PrintLines(m1, fill)
  388.     /* get the wife's data */
  389.     m1 = g1||GetPersonStr(GENTREE.ct1)
  390.     PrintLines(m1, fill)
  391.     PrintLF()  
  392.     if prtrev then
  393.       currgen = currgen - 1
  394.     else
  395.       currgen = currgen + 1
  396.     np = np % 2
  397.   end
  398.   g1 = GetGenStr(currgen, fill)||GetPersonStr(GENTREE.np)
  399.   g1 = g1||GetMarriages(GENTREE.np)
  400.   PrintLines(g1, fill)
  401.   PrintLF()
  402. end
  403. else do
  404.   /* print all */
  405.   if prtrev then
  406.     currgen = currgen - 1
  407.   else
  408.     currgen = 1
  409.   fill = 6
  410.  
  411.   g1 = center("Generation: "||GetGenStr(currgen, fill), plwidth-1)
  412.   PrintLines(g1, fill)
  413.   g1 = "1.    "||GetPersonStr(GENTREE.1)
  414.   g1 = g1||GetMarriages(GENTREE.1)
  415.   PrintLines(g1, fill)
  416.   if prtopt > 2 then
  417.     PrintSiblings(GENTREE.1, 1)
  418.   PrintLF()  
  419.  
  420.   np = 2
  421.   if prtrev then
  422.     currgen = currgen - 1
  423.   else
  424.     currgen = currgen + 1
  425.   do while np < numpers
  426.     g1 = center("Generation: "||GetGenStr(currgen, fill), plwidth)
  427.     PrintLines(g1, fill)
  428.     endnum = 2*np-1
  429.     do ct = np to endnum by 2
  430.       ct1 = ct + 1
  431.       ct2 = ct % 2
  432.       /* print the principal data */
  433.       if GENTREE.ct ~= 0 then do
  434.         g1 = left(ct||".    ",fill)||GetPersonStr(GENTREE.ct)
  435.  
  436.     GETPARENTS GENTREE.ct2
  437.     mf1 = RESULT
  438.     EXISTFAMILY mf1
  439.     if RESULT = 'YES' then
  440.       m1 = GetMarriageStr(mf1)
  441.     else
  442.       m1 = ""
  443.  
  444.         if m1 ~= "" then
  445.           m1 = g1||", m: "||m1
  446.         else m1 = g1
  447.         g1 = copies(' ',fill)
  448.         PrintLines(m1, fill)
  449.         if prtopt = 4 then
  450.           PrintSiblings(GENTREE.ct, ct)
  451.       end
  452.       /* print the spouse data */
  453.       if GENTREE.ct1 ~= 0 then do
  454.         m1 = left(ct1||".    ",fill)||GetPersonStr(GENTREE.ct1)
  455.         PrintLines(m1, fill)
  456.         if prtopt = 4 then
  457.           PrintSiblings(GENTREE.ct1, ct1)
  458.       end
  459.     end
  460.     PrintLF()  
  461.     if prtrev then
  462.       currgen = currgen - 1
  463.     else
  464.       currgen = currgen + 1
  465.     np = np * 2
  466.   end
  467. end
  468. if numgens = 1 then
  469.   PrintLines("No ancestors are recorded for this person.", 0)
  470.  
  471. writech(prtdev, prtnlqoff); /* ESC[1"z NLQ off */
  472. EndString("Done.")
  473.  
  474. EXIT
  475.  
  476. /* Parse command line arguments and set the appropriate global variables */
  477. ParseArguments:
  478. if noirn = "NOIRN" then useirn = 0
  479. else if noirn = "QUIET" || noirn = "NOREQ" then do
  480.   outval = noirn
  481.   noirn = ""
  482. end
  483. else do
  484.   outval = mgen
  485.   mgen = noirn
  486.   noirn = ""
  487. end
  488. if mgen = "QUIET" || mgen = "NOREQ" then do
  489.   outval = mgen
  490.   mgen = ""
  491. end
  492.  
  493. MaxGens = 20
  494. /* due to the Roman numbers, we can't handle more than 40 */
  495. /* but due to speed limitations, I don't advise using more than 20 */
  496. if mgen ~= "" then do
  497.   if DATATYPE(mgen, 'w') & mgen > 0 & mgen < MaxGens then
  498.     MaxGens = mgen
  499. end
  500.  
  501. if outval = "QUIET" then do
  502.   usereq = 0
  503.   outp = 0
  504. end
  505. else if outval = "NOREQ" then
  506.   usereq = 0
  507.  
  508. /* if outname = "" then outname = 'STDOUT' */
  509.  
  510. if prtin = "" then do
  511.   prtopt = 0
  512.   if ~outp then EndString("Requires argument is missing.")
  513.     /* actually, with outp = 0, all it does is EXIT */
  514. end
  515. else do
  516.   prtopt = CheckAnswer(prtin)
  517.   /* Note that it was important to establish outp before calling these */
  518. end  
  519.  
  520. return 0
  521.  
  522. OpenPrinter:
  523. /* Open the printer device and print out a nice header */
  524. if outname = 'STDOUT' then
  525.   prtdev = scrdev
  526. else do
  527.   prtdev = "PRINTER"
  528.   if ~open(prtdev, outname, 'w') then
  529.     EndString("ERROR: Failed to open output file!")
  530. end
  531. writech(prtdev, prtinit||prtnlqon)
  532. if prtopt = 1 then
  533.   prtstr = "FOREFATHERS (Male ancestor line only)"
  534. else if prtopt = 2 then
  535.   prtstr = "PEDIGREE CHART; No siblings"
  536. else if prtopt = 3 then
  537.   prtstr = "PEDIGREE CHART; Only siblings of proband"
  538. else
  539.   prtstr = "PEDIGREE CHART; All siblings"
  540. prtstr = prtundon||prtdson||prtstr||prtdsoff||prtundoff
  541. DoWrite(prtdev, prtstr)
  542. prtstr = prtdson||"Report printed on: "||date()||prtdsoff
  543. DoWrite(prtdev, prtstr)
  544. prtstr = copies('=', plwidth)
  545. DoWrite(prtdev, prtstr)
  546. return 0
  547.  
  548. PrintLines: PROCEDURE EXPOSE prtdev plwidth prtopt pgline pgsize
  549. parse arg ostr, fill
  550. /* TO DO:
  551.  * if there are control strings within ostr (like prtdson or prtdsoff)
  552.  * don't include them in the length count
  553.  */
  554. do while ostr ~= ""
  555.   nnl = plwidth+1
  556.   if length(ostr) > plwidth then do
  557.     do until pc = ' ' | nnl = 1
  558.       pc = substr(ostr, nnl, 1)
  559.       nnl = nnl - 1
  560.     end
  561.     if nnl = 1 then do
  562.       prtstr = left(ostr, plwidth)
  563.       ostr = delstr(ostr, 1, nnl)
  564.     end
  565.     else do
  566.       prtstr = left(ostr, nnl)
  567.       ostr = delstr(ostr, 1, nnl+1)
  568.     end
  569.   end
  570.   else do
  571.     prtstr = ostr
  572.     ostr = ""
  573.   end
  574.   DoWrite(prtdev, prtstr)
  575.   if ostr ~= "" then
  576.     ostr = copies(' ',fill)||ostr
  577. end
  578. return 0
  579.  
  580. PrintLF:
  581. DoWrite(prtdev, "")
  582. return 0
  583.  
  584. PrintSiblings: PROCEDURE EXPOSE prtdev plwidth prtopt useirn pgline pgsize
  585. parse arg inum, prenum
  586. GETPARENTS inum
  587. famfgrn = RESULT
  588. EXISTFAMILY famfgrn
  589. if RESULT ~= 'YES' then return 0; /* no parents, then no siblings */
  590. ix = 0; chnum = 0
  591. do until ischld ~= 'YES'
  592.   GETCHILD famfgrn ix
  593.   prsn = RESULT
  594.   EXISTPERSON prsn
  595.   ischld = RESULT
  596.   if ischld = 'YES' then do
  597.     chnum = chnum + 1
  598.     /* skip a number for person <inum> to indicate where he fits in */
  599.     if prsn ~= inum then do
  600.       ostr = copies(' ',8)||prenum||D2C(chnum+96)". "||GetPersonStr(prsn)
  601.       PrintLines(ostr, 11)
  602.       if chnum = 26 then return 0; /* 'z': can't handle more than 26 children */
  603.     end
  604.   end
  605.   ix = ix + 1
  606. end
  607. return 0
  608.  
  609. GetGenStr: PROCEDURE EXPOSE prtopt GenerationS.
  610. parse arg gnum, fill
  611. if gnum <= 20 then
  612.   gstr = word(GenerationS.1, gnum)
  613. else if gnum <= 40 then
  614.   gstr = word(GenerationS.2, gnum)
  615. else
  616.   return "["||gnum||"]"
  617. if prtopt = 1 then gstr = left(gstr||".     ",fill)
  618. return gstr
  619.  
  620. GetPersonStr: PROCEDURE EXPOSE useirn
  621. parse arg irn
  622. if irn ~= 0 then do
  623.   nstr = GetNameStr(irn)
  624.   nstr = nstr||GetBirthStr(irn)
  625.   nstr = nstr||GetDeathStr(irn)
  626. end
  627. else
  628.   nstr = "UNKNOWN"
  629. return nstr
  630.  
  631. GetNameStr: PROCEDURE EXPOSE useirn
  632. parse arg gnum
  633. /* prtdson = '1B'x||"[1m";    * ESC[1m boldface on    */
  634. /* prtdsoff = '1B'x||"[22m";  * ESC[22m boldface off  */
  635. GETFIRSTNAME gnum
  636. name = RESULT
  637. if name ~= "" then name = name||" "
  638. GETLASTNAME gnum
  639. lname = RESULT
  640. if lname = "" then lname = "UNKNOWN"
  641. name = name||lname
  642. /* another option: name = name||prtdson||lname||prtdsoff
  643.  * Problem: see PrintLines
  644.  */
  645. if useirn then name = name||" ["gnum"]"
  646. return name
  647.  
  648. GetBirthStr: PROCEDURE
  649. parse arg gnum
  650. GETBIRTHPLACE gnum
  651. bstr = RESULT
  652. GETBIRTHDATE gnum
  653. bdat = RESULT
  654. if bdat ~= "" & bstr ~= "" then bstr = bstr||" "
  655. bstr = bstr||bdat
  656. if bstr ~= "" then bstr = ", b: "||bstr
  657. return bstr
  658.  
  659. GetDeathStr: PROCEDURE
  660. parse arg gnum
  661. GETDEATHPLACE gnum
  662. dstr = RESULT
  663. GETDEATHDATE gnum
  664. ddat = RESULT
  665. if ddat ~= "" & dstr ~= "" then dstr = dstr||" "
  666. dstr = dstr||ddat
  667. if dstr ~= "" then dstr = ", d: "||dstr
  668. return dstr
  669.  
  670. GetMarriages: PROCEDURE EXPOSE useirn
  671. parse arg irn
  672. mstr = ""
  673. GETMARRIAGE irn 0
  674. mf = RESULT
  675. EXISTFAMILY mf
  676. if RESULT = 'YES' then do
  677.   mtrue = 1
  678.   GETMARRIAGE irn 1
  679.   m2 = RESULT
  680.   EXISTFAMILY m2
  681.   if RESULT = 'YES' then mset = 1
  682.   else mset = 0
  683. end
  684. else
  685.   mtrue = 0  
  686. mnum = 0
  687. do while mtrue
  688.   m1 = GetMarriageStr(mf)
  689.   if m1 ~= "" then m1  = m1||' '
  690.   ptn = GetPartnerIRN(mf, irn)
  691.   m1 = m1||GetPersonStr(ptn)
  692.  
  693.   mnum = mnum + 1
  694.   if mset then mstr = mstr||", m("||mnum||"): "||m1
  695.   else mstr = mstr||", m: "||m1
  696.  
  697.   GETMARRIAGE irn mnum
  698.   mf = RESULT
  699.   EXISTFAMILY mf
  700.   if RESULT ~= 'YES' then mtrue = 0
  701. end
  702. return mstr
  703.  
  704. GetMarriageStr: PROCEDURE
  705. parse arg mf
  706. GETMARRYPLACE mf
  707. mstr = RESULT
  708. GETMARRYDATE mf
  709. mdat = RESULT
  710. if mdat ~= "" & mstr ~= "" then mstr = mstr||" "
  711. mstr = mstr||mdat
  712. return mstr
  713.  
  714. GetParentsIRN: PROCEDURE EXPOSE GENTREE.
  715. parse arg fnum, ct, ct1
  716. fath = 0; moth = 0
  717. GETSPOUSE fnum
  718. sps = RESULT
  719. EXISTPERSON sps
  720. if RESULT = 'YES' then do
  721.   GETSEX sps
  722.   if RESULT = 'M' then
  723.     fath = sps
  724.   else moth = sps
  725. end
  726. GETPRINCIPAL fnum
  727. prn = RESULT
  728. /* If there are two mothers, or two fathers, then name the principal
  729.  * as 'father' and the spouse as 'mother'
  730.  */
  731. EXISTPERSON prn
  732. if RESULT = 'YES' then do
  733.   GETSEX prn
  734.   if RESULT = 'M' then do
  735.     if fath ~= 0 then
  736.       moth = sps
  737.     fath = prn
  738.   end
  739.   else if moth ~= 0 then
  740.     fath = prn
  741.   else
  742.     moth = prn
  743. end
  744. GENTREE.ct = fath
  745. GENTREE.ct1 = moth
  746. return 0
  747.  
  748. GetPartnerIRN: PROCEDURE
  749. parse arg fnum, inum
  750. GETPRINCIPAL fnum
  751. prn = RESULT
  752. GETSPOUSE fnum
  753. sps = RESULT
  754. if inum = prn then pnum = sps
  755. else if inum = sps then pnum = prn
  756. else pnum = 0
  757. return pnum
  758.  
  759. CheckAnswer: PROCEDURE EXPOSE outp prtdev usereq scrdev
  760. parse arg str
  761. str = left(str, 1)
  762. if ~DATATYPE(str, 'w') | (str < 1 | str > 4) then
  763.   EndString("Invalid option - aborted.")
  764. return  str
  765.  
  766. /*
  767.  * output at most #pgsize lines per page to the print device
  768.  * if pgsize = 0, this feature is turned off (unlimited #lines per page)
  769.  */
  770. DoWrite: PROCEDURE EXPOSE pgline pgsize
  771. parse arg prtdev, ostr
  772. if pgsize ~= 0 & pgline > pgsize then do
  773.   writech(prtdev, '0C'x); /* CTRL-L; next page */
  774.   pgline = 0
  775. end
  776. writeln(prtdev, ostr)
  777. pgline = pgline + 1
  778. return 0
  779.  
  780. Tell: PROCEDURE EXPOSE outp scrdev
  781. parse arg str
  782. if outp then
  783.   writeln(scrdev, str)
  784. return 0
  785.  
  786. TellNN: PROCEDURE EXPOSE outp scrdev
  787. /* Tell, No Newline */
  788. parse arg str
  789. if outp then
  790.   writech(scrdev, str)
  791. return 0
  792.  
  793. EndString: PROCEDURE EXPOSE outp prtdev usereq scrdev pscr
  794. parse arg str
  795. /* If you turned off stdout, no error messages will be shown! */
  796. if usereq then
  797.   rtezrequest(str,'E_xit','PrintPedigree Message:','rt_pubscrname = '||PSCR)
  798. else do
  799.   Tell(str || '0A'x)
  800. end
  801. if outp & ~usereq & (scrdev ~= stdout) then do
  802.   Tell("Press <return> to exit.")
  803.   readln(scrdev)
  804.   close(scrdev)
  805. end
  806. close(prtdev)
  807. EXIT
  808.  
  809. /* Let's make sure you get a nice message when you turn off the printer :-) */
  810.  
  811. IOERR:
  812.   bline = SIGL
  813.   say "I/O error #"||RC||" detected in line "||bline||":"
  814.   say sourceline(bline)
  815.   EXIT
  816.